#include "base/logging.h"
#include "call_center_cache.h"

#include "base/config_reader.h"
#include "database/scoped_connection.h"
#include "database/simple_db_pool.h"

#include "rpc_thread_manager.h"

#include <string>

namespace imserver {

using apache::thrift::concurrency::Runnable;
class ReloadCallCenterCacheTask : public Runnable  {
 public:
  ReloadCallCenterCacheTask(){}
  virtual void run() {
    CallCenterCache::Instance().Reload();
    GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadCallCenterCacheTask()), 143 * 1000);
  }
};

CallCenterCache::CallCenterCache() : db_conn_pool_(NULL) {
  ConfigReader config("../conf/message_exchange_service.conf");

  db_conn_pool_ = new base::SimpleConnectionPool(config.Get("shop_db", "name").c_str(),
                      config.Get("shop_db", "server_list").c_str(),
                      config.Get("shop_db", "user").c_str(),
                      config.Get("shop_db", "password").c_str());
  GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadCallCenterCacheTask()), 30 * 1000);
}

bool CallCenterCache::IsWaiter(int64_t uid) const {
  boost::shared_lock<boost::shared_mutex> rlock(waiters_mutex_);

  std::set<int64_t>::const_iterator it = waiters_.find(uid);
  LOG_DEBUG("uid " << uid << " IsWaiter=" << (it != waiters_.end()));
  return it != waiters_.end();
}

bool CallCenterCache::IsCallCenter(int64_t uid) const {
  boost::shared_lock<boost::shared_mutex> rlock(call_centers_mutex_);

  std::set<int64_t>::const_iterator it = call_centers_.find(uid);
  LOG_DEBUG("uid " << uid << " IsCallCenter=" << (it != call_centers_.end()));
  return it != call_centers_.end();
}

int CallCenterCache::Reload() {
  if (db_conn_pool_ == NULL) {
    LOG_ERROR("CallCenterCache::Reload failed on NULL database-pool.");
    return -1;
  }

  mysqlpp::ScopedConnection db(*db_conn_pool_);
  if (!db) {
    LOG_ERROR("CallCenterCache::Reload failed to get a connection from database-pool.");
    return -1;
  }

  std::set<int64_t> waiters;
  std::set<int64_t> call_centers;

  mysqlpp::Query query(db->query());
  query << "SELECT shop, waiter FROM shop_waiters";

  try {
    mysqlpp::UseQueryResult ret = query.use();
    if (ret) {
      while(mysqlpp::Row row = ret.fetch_row()) {
        waiters.insert((int64_t)row["waiter"]);
        call_centers.insert((int64_t)row["shop"]);
        LOG_DEBUG("CallCenterCache::Reload shop " << row["shop"]
                  << " waiter=" << row["waiter"]);
      }
    }
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR("CallCenterCache::Reload " << query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -2;
  }

//call_centers.insert(127646892);

//waiters.insert(288297970);
//waiters.insert(382097274);
//waiters.insert(101);
//waiters.insert(201);

  LOG_ERROR("CallCenterCache::Reload OK, waiters=" << waiters.size() << " call_ceners=" << call_centers.size());

  {
    boost::unique_lock<boost::shared_mutex> wlock(waiters_mutex_);
    waiters_.swap(waiters);
  }

  {
    boost::unique_lock<boost::shared_mutex> wlock(call_centers_mutex_);
    call_centers_.swap(call_centers);
  }
  return 0;
}

}

